#include "OdbcResult.h"

#if defined( WIN32 ) || defined ( WIN64 )

#include "OdbcResultSetMetaData.h"

LIBDBC_BEGIN_NAMESPACE

OdbcResult::OdbcResult(SQLHSTMT hstmt, SQLHDBC hdbc)
{
	_hResult = hstmt;
	_hdbc = hdbc;
	_cols = 0;

	if (_hResult)
	{
		SQLNumResultCols(_hResult, (SQLSMALLINT*)&_cols);
	}

	_metaData = new OdbcResultSetMetaData(this);
}

OdbcResult::~OdbcResult()
{
	if (_hResult)
	{
		SQLCloseCursor(_hResult);
		SQLFreeStmt(_hResult, SQL_CLOSE);
	}
	if (_hdbc)
	{
		SQLRETURN disconnected = SQLDisconnect(_hdbc);
		SQLFreeHandle(SQL_HANDLE_DBC, _hdbc);
	}
}

unsigned int OdbcResult::getColumnCount()
{
	return _cols;
}

char* OdbcResult::getFieldName(int field, char* buffer, int len)
{
	SQLSMALLINT bufLen, nameLen, type, decimal, nullable;
#ifdef _M_IX86
	//32bit
	SQLUINTEGER colSize;
#else
	//64bit
	SQLULEN colSize;
#endif

	bufLen = len;

	SQLDescribeCol(_hResult, field + 1, (unsigned char*)buffer, bufLen, &nameLen, &type, &colSize, &decimal, &nullable);

	// SQL_DESC_BASE_COLUMN_NAME
	// SQLColAttribute( m_hStmt, (SQLSMALLINT)field+1, SQL_DESC_NAME, pszBuffer, 200, &length, NULL);
	return buffer;

}

bool OdbcResult::next()
{
	bool bNext = false;
	if (_hResult)
	{
		bNext = ODBCSUCCESS(SQLFetch(_hResult));
	}
	return bNext;
}

char* OdbcResult::getString(int field, char* buffer, int len)
{
	if (buffer == NULL || !_hResult || len == 0) return NULL;
	*buffer = 0;

	SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_CHAR, buffer, len, NULL);

	return buffer;
}

int OdbcResult::getInt(int field)
{
	int value = 0;
	SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_SSHORT, &value, sizeof(int), NULL);
	return value;
}

long OdbcResult::getLong(int field)
{
	long value;
	SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_SLONG, &value, sizeof(long), NULL);
	return value;
}

double OdbcResult::getDouble(int field)
{
	double value = 0;
	SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_DOUBLE, &value, sizeof(double), NULL);
	return value;
}


// Version >0.8 API
bool OdbcResult::getStringExt(int field, char* buffer, int len)
{
	if (buffer == NULL || !_hResult || len == 0) {
		return false;
	}
	*buffer = 0;

	SQLRETURN result = SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_CHAR, buffer, len, NULL);
	_errorcode = (int)result;
	return result == SQL_SUCCESS;
}

bool OdbcResult::getInt(int field, int* pvalue)
{
	SQLRETURN result = SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_SSHORT, pvalue, sizeof(int), NULL);
	_errorcode = (int)result;
	return result == SQL_SUCCESS;
}

bool OdbcResult::getLong(int field, long* pvalue)
{
	SQLRETURN result = SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_LONG, pvalue, sizeof(long), NULL);
	_errorcode = (int)result;
	return result == SQL_SUCCESS;
}

bool OdbcResult::getDouble(int field, double* pvalue)
{
	SQLRETURN result = SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_DOUBLE, pvalue, sizeof(double), NULL);
	_errorcode = (int)result;
	return result == SQL_SUCCESS;
}

bool OdbcResult::getBinaryLength(int field, unsigned long* len)
{
#ifdef _M_IX86
	SQLINTEGER* sqllen = (SQLINTEGER*)len;
#else
	SQLLEN* sqllen = (SQLLEN*)len;
#endif

	SQLRETURN result = SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_BINARY, NULL, 0, sqllen);
	if (result == SQL_SUCCESS_WITH_INFO) _errorcode = 0; else _errorcode = (int)result;
	return result == SQL_SUCCESS_WITH_INFO;
}

bool OdbcResult::getBinary(int field, unsigned char* pBuffer, int buflen)
{

#ifdef _M_IX86
	SQLINTEGER* sqllen = (SQLINTEGER*)&buflen;
#else
	// _M_X64
	SQLLEN* sqllen = (SQLLEN*)&buflen;
#endif
	SQLRETURN result = SQLGetData(_hResult, (SQLUSMALLINT)field + 1, SQL_C_BINARY, pBuffer, buflen, sqllen);
	if (result == SQL_SUCCESS) _errorcode = 0; else _errorcode = (int)result;
	return result == SQL_SUCCESS;
}

LIBDBC_END_NAMESPACE

#endif 
